
// VS_BEGIN
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aCoord;
layout (location = 2) in vec3 aNormal;
layout (location = 3) in vec3 aTangent;
layout (location = 4) in vec3 aBitangent;

uniform mat4 u_model;

layout (std140) uniform EngineUBO
{
    mat4 u_view;
    mat4 u_project;
    vec3 u_camPos;
    vec3 u_camInfo;
    mat4 u_inversePV;
};

out vec2 g_texCoord;

void main() {
    gl_Position = vec4(aPos, 1.0f);
    g_texCoord = aCoord;
}
// VS_END

// FS_BEGIN
#version 330 core 

// Light Packet:
// position.x position.y position.z type(PointLight: 0; DirectLight: 1; AmbientSphereLight: 2)
// color.r    color.g    color.b    strength
// direct.x   direct.y   direct.z   unuse
// unuse      unuse      unuse      unuse
layout (std140) uniform LightUBO
{
    mat4 u_lights[64];
    int u_lightNum;
};

layout (std140) uniform EngineUBO
{
    mat4 u_view;
    mat4 u_project;
    vec3 u_camPos;
    vec3 u_camInfo;
    mat4 u_inversePV;
};

in vec2 g_texCoord;


uniform samplerCube u_irradianceMap; 

uniform sampler2D u_positionRT;
uniform sampler2D u_normalRT;
uniform sampler2D u_tangentRT;
uniform sampler2D u_depthRT;
uniform sampler2D u_albedoRT;


out vec4 FragColor;

void main() {
    vec2 texSize = textureSize(u_depthRT, 0).xy;
    vec2 uv = gl_FragCoord.xy / texSize;

    mat4 vp = u_project * u_view;

    vec2 near_far = vec2(u_camInfo.y, u_camInfo.z);

    // 背景不参与计算
    float worldDepth = texture(u_depthRT, g_texCoord).x / (near_far.y - near_far.x);
    if (0.0f >= worldDepth) {
        FragColor = vec4(0.0f);
        return;
    }

    // 计算反射方向（世界空间）
    vec3 worldPos = texture(u_positionRT, g_texCoord).xyz;
    vec3 worldNormal = texture(u_normalRT, g_texCoord).xyz;
    vec3 camDir = normalize(worldPos - u_camPos);
    vec3 refDir = normalize(reflect(camDir, worldNormal));

    float thickness = 0.05f;
    // 反射光线最远传播距离
    float max_step_dist = 15.0f;
    vec3 start_pos_world = worldPos + refDir * 0.0f;
    vec3 end_pos_world = worldPos + refDir * max_step_dist;
    // 将起始点和终点转为NDC空间
    vec4 start_pos_clip = vp * vec4(start_pos_world, 1.0f);
    vec4 end_pos_clip = vp * vec4(end_pos_world, 1.0f);
    vec3 start_pos_ndc = start_pos_clip.xyz / start_pos_clip.w; // [-1, 1]
    vec3 end_pos_ndc = end_pos_clip.xyz / end_pos_clip.w; // [-1, 1]
    vec3 diff_ndc = end_pos_ndc - start_pos_ndc;

    // 将起始点和终点转换为屏幕空间[0, texSize]
    vec2 start_pos_screen = vec2(0.0f);
    start_pos_screen = (start_pos_ndc.xy + 1.0f) / 2.0f * texSize;
    vec2 end_pos_screen = vec2(0.0f); 
    end_pos_screen = (end_pos_ndc.xy + 1.0f) / 2.0f * texSize;


    vec2 diff_pos_screen = end_pos_screen - start_pos_screen;
    int sample_count = min(int(max(abs(diff_pos_screen.x), abs(diff_pos_screen.y))), 512); // 选择长边作为采用点,限制采样点数最多为512
    vec2 delta_diff = diff_pos_screen / float(sample_count); // 计算步进距离
    vec3 delta_diff_ndc = diff_ndc / float(sample_count);


    // 步进比较深度
    FragColor = vec4(0.0f);
    for (int i = 1; i < sample_count; ++i) {
        vec2 current_screen = start_pos_screen + delta_diff * i;
        vec2 uv = current_screen / texSize; // [0, 1]
        if (uv.x <= 0.0f || uv.x >= 1.0f || uv.y <= 0.0f || uv.y >= 1.0f) {
            break;
        }
        // 获取当前uv下缓存中世界空间坐标
        vec3 current_ndc = start_pos_ndc + delta_diff_ndc * i;
        // ndc -> 世界空间
        vec4 current_world_temp = u_inversePV * vec4(current_ndc, 1.0f);
        vec3 current_world = current_world_temp.xyz / current_world_temp.w; // 透视变换

        // 采样深度
        float sample_depth = texture(u_depthRT, uv).x;
        float p_depth = distance(u_camPos, current_world);
        bool isHit = p_depth > sample_depth && p_depth < sample_depth + thickness;
        if (isHit) {
            FragColor = vec4(texture(u_albedoRT, uv).xyz, 0.5f);
        }
    }
}



// FS_END
